home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Aminet 30
/
Aminet 30 (1999)(Schatztruhe)[!][Apr 1999].iso
/
Aminet
/
util
/
cli
/
WBLaunch.lha
/
Source
/
wblaunch.c
< prev
Wrap
C/C++ Source or Header
|
1999-02-14
|
11KB
|
380 lines
/*
* wblaunch.c - WBLaunch main routines
* part of WBLaunch - emulates WB startup of programs from the Shell
* Copyright (C) 1998, 1999 Stephen Williams <sw@fysh.org>
* wbstart.library is copyright (C) Stefan Becker
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
#include <exec/memory.h>
#include <dos/dos.h>
#include <libraries/wbstart.h>
#include <workbench/startup.h>
#include <clib/dos_protos.h>
#include <clib/exec_protos.h>
#include <clib/wbstart_protos.h>
#ifdef VBCC
#include <inline/dos_protos.h>
#include <inline/exec_protos.h>
#endif
#include <string.h>
/* Library bases */
extern struct DosLibrary * DOSBase;
extern struct Library * SysBase;
struct Library * WBStartBase;
/* Constants for my readargs array */
#define ARG_PROGRAM 0
#define ARG_ARGUMENTS 1
#define ARG_PRI 2
#define ARG_VERBOSE 3
/* String for c:Version */
const char Version[] = "\0$VER: WBLaunch 1.1 (14.2.99)";
/* WBStart library name */
const char WBStartName[] = "wbstart.library";
/* Text for extended help */
const char Verbose[] =
"Copyright © 1998, 1999 Stephen Williams <sw@fysh.org>\n"
"wbstart.library is copyright © Stefan Becker\n"
"See WBLaunch.readme for terms of distribution";
/*
* Functions
*/
/*
* NAME:
* findFile - find directory in path containing a given file
*
* SYNOPSIS:
* fileLock = findFile(filename)
* BPTR findFile(char *)
*
* FUNCTION:
* This routine searches the path for the given filename. The
* current directory is searched first. If the file is not
* found there, the path is searched.
*
* INPUTS:
* filename - pointer to a null-terminated string
*
* RESULTS:
* fileLock - BCPL pointer to a lock on the directory containing
* the file, or 0 for failure
*
* NOTE:
* It is your responsibility to unlock fileLock when you have
* finished with it.
*
*/
BPTR findFile(char * fileName)
{
BPTR fileLock;
BPTR * pathPtr;
BPTR prevDir;
/* Try current directory */
if(fileLock = Lock(fileName, SHARED_LOCK)) {
#if DEBUG
Printf("Found \"%s\" in current directory\n", fileName);
#endif
UnLock(fileLock);
return DupLock(((struct Process *)FindTask(NULL))->pr_CurrentDir);
}
/*
* Not there? Look in the path. This path traversal code is
* Deep Magic. Don't blame me if you don't understand it.
* Neither do I any more ;-) Future versions of this program
* will use dospath.library instead
*/
for(pathPtr = (BPTR *)(((struct CommandLineInterface *)(((struct Process *)FindTask(NULL))->pr_CLI << 2))->cli_CommandDir << 2);
pathPtr != NULL; pathPtr = (BPTR *)(pathPtr[0] << 2)) {
prevDir = CurrentDir(pathPtr[1]);
fileLock = Lock(fileName, SHARED_LOCK);
(void)CurrentDir(prevDir);
if(fileLock) {
#if DEBUG
Printf("Found \"%s\" in path\n", fileName);
#endif
UnLock(fileLock);
return DupLock(pathPtr[1]);
}
}
return 0L;
}
/*
* Entry point
*
* Called from custom startup code.
*
* INPUTS:
* None.
*
* RESULT:
* AmigaDOS error code (0=OK, 5=WARN, 10=ERROR or 20=FAIL).
*
*/
int shellmain(void)
{
struct RDArgs * anchor;
int argCount = 0;
char ** arguments;
char * argv0 = (char *)((((struct CommandLineInterface *)(((struct Process *)FindTask(NULL))->pr_CLI << 2))->cli_CommandName << 2) + 1);
char * name;
int rc = 20;
LONG rdargs[4] = {0L, 0L, 0L, 0L};
/* ReadArgs parsing */
anchor = ReadArgs("PROGRAM/A,ARGS/M,PRI=PRIORITY/N/K,VERBOSE/S",
&rdargs[0], NULL);
if(anchor) {
BPTR fileOpen;
BPTR newDirectory = 0L;
BPTR oldDirectory =
((struct Process *)FindTask(NULL))->pr_CurrentDir;
int pathLen;
char * pathStr = 0L;
/* Got appropriate arguments */
name = (char *)rdargs[ARG_PROGRAM];
/* Count arguments passed as ARGS/M */
for(arguments = (char **)rdargs[ARG_ARGUMENTS];
(arguments != NULL) && (*arguments != NULL);
arguments++)
argCount++;
arguments = (char **)rdargs[ARG_ARGUMENTS];
/* See if the filename has no directory part. We'll need to change
directory if this is the case */
if(!(pathLen = (int)FilePart(name) - (int)name)) {
/* Find the file in the current directory or path */
newDirectory = findFile(name);
} else {
/* Got a path part; change dir to there */
if(pathStr = AllocVec(pathLen + 4, MEMF_CLEAR | MEMF_REVERSE)) {
strncat(pathStr, name, pathLen);
#ifdef DEBUG
Printf("Locking directory \"%s\", ", pathStr);
#endif
newDirectory = Lock(pathStr, SHARED_LOCK);
/*oldDirectory = CurrentDir(newDirectory);*/
#ifdef DEBUG
Printf("lock = %lx\n", newDirectory);
#endif
}
}
/* Make sure file exists */
(void)CurrentDir(newDirectory);
if(fileOpen = Open(FilePart(name), MODE_OLDFILE)) {
ULONG firstLong = 0;
/* Read first longword */
(void)Read(fileOpen, &firstLong, 4);
Close(fileOpen);
(void)CurrentDir(oldDirectory);
/*
* Make sure we got an executable file header.
* NB: This will FAIL for binaries not in hunk format (e.g. ELF);
* this needs fixing in some way!
*
* I could just not bother with the check, but then wbstart.library
* might choke if someone passes a text file or something in.
*
* Maybe I should check for ELF headers as well?
* Or maybe ELF users should all change to WarpUp ;-)
*/
if(firstLong == 0x000003f3) {
struct Library * privWBStartBase;
/* Open library */
if(privWBStartBase = OpenLibrary((char *)WBStartName,
(ULONG)WBSTART_VERSION)) {
int goodArgs = 0;
int count;
struct WBArg *wbArgs = NULL;
/* Do Workbench argument parse */
if(argCount > 0) {
if(wbArgs = AllocVec(argCount * sizeof(struct WBArg),
MEMF_ANY | MEMF_REVERSE)) {
char * argDir;
char * fname;
struct WBArg * nextArg = wbArgs;
/* Process arguments one at a time */
#ifdef DEBUG
Printf("Received %ld arguments\n", (ULONG)argCount);
#endif
for(count = 0; count < argCount; count++) {
/* Go back to starting directory */
BPTR tempFile = Lock(arguments[count], SHARED_LOCK);
#ifdef DEBUG
Printf("Processing arg #%ld, \"%s\":\n",
(ULONG)(count + 1),
arguments[count]);
#endif
/* Try to open the file */
if(tempFile) {
UnLock(tempFile);
/* Allocate temp space */
if(argDir =
AllocVec(strlen(arguments[count]),
MEMF_REVERSE | MEMF_CLEAR)) {
fname = FilePart(arguments[count]);
/* See if there's a directory component */
if(fname == arguments[count]) {
/* No, it's relative to start directory */
/* Need to DupLock() so we can safely UnLock() */
nextArg->wa_Lock = DupLock(oldDirectory);
nextArg->wa_Name = arguments[count];
nextArg++;
goodArgs++;
#ifdef DEBUG
Printf(" Located relative to current directory\n");
#endif
} else {
BPTR argLock;
strncat(argDir, arguments[count],
(int)(fname - arguments[count]));
argLock = Lock(argDir, SHARED_LOCK);
/* Attempt lock on directory */
if(argLock) {
/* Got it; use that lock and the
filename component */
nextArg->wa_Lock = argLock;
nextArg->wa_Name = fname;
nextArg++;
goodArgs++;
#ifdef DEBUG
Printf(" Located in directory \"%s\"\n", argDir);
#endif
} else {
#ifdef DEBUG
Printf(" Couldn't lock this argument\n");
#endif
}
}
FreeVec(argDir);
}
} else {
Printf("%s warning: couldn't locate argument \"%s\"\n",
argv0, arguments[count]);
#ifdef DEBUG
Printf(" Couldn't locate this argument\n");
#endif
}
}
} else Printf("%s warning: couldn't allocate memory for arguments\n", argv0);
}
/* Start the process */
if(newDirectory) {
char * argString;
#ifdef DEBUG
Printf("Starting process with %ld arguments\n", goodArgs);
#endif
/* Verbose? */
if(rdargs[ARG_VERBOSE] &&
(argString = AllocVec(512L, MEMF_ANY | MEMF_REVERSE))) {
Printf("\n\033[1m%s\033[0m\n%s\n\n",
&Version[7], &Verbose[0]);
NameFromLock(newDirectory, argString, 511L);
AddPart(argString, FilePart(name), 511L);
Printf("Launching \"%s\" with %ld arguments%s", argString,
goodArgs, goodArgs ? ":\n" : "\n");
for(count = 0; count < goodArgs; count++) {
NameFromLock(wbArgs[count].wa_Lock, argString, 511);
Printf(" Argument #%ld: \"%s\", directory \"%s\"\n",
(ULONG)(count + 1),
wbArgs[count].wa_Name,
argString);
}
Printf("\n");
FreeVec(argString);
}
WBStartBase = privWBStartBase;
rc = !WBStartTags(
WBStart_Priority, rdargs[ARG_PRI] ? *(ULONG *)rdargs[ARG_PRI] : 0,
WBStart_ArgumentCount, goodArgs,
WBStart_ArgumentList, goodArgs ? wbArgs : NULL,
WBStart_Name, FilePart(name),
WBStart_DirectoryLock, newDirectory,
0
) ? 0 : 10;
#ifdef DEBUG
Printf("Process started\n");
#endif
} else Printf("%s: initialization failed\n", argv0);
/* Close things */
if(wbArgs) {
register int count;
/* Unlock all the directories we locked */
for(count = 0; count < goodArgs; count++)
UnLock(wbArgs[count].wa_Lock);
FreeVec(wbArgs);
}
CloseLibrary(privWBStartBase);
} else Printf("%s: couldn't open %s v%ld+\n", argv0, WBStartName,
(ULONG)WBSTART_VERSION);
} else PrintFault(ERROR_OBJECT_WRONG_TYPE, argv0);
} else {
Printf("%s: couldn't open \"%s\"\n", argv0, name);
(void)CurrentDir(oldDirectory); /* changed prior to Open() */
}
if(pathStr) FreeVec(pathStr);
/* Change directory back to where we started */
if(newDirectory) {
/*(void)CurrentDir(oldDirectory);*/
UnLock(newDirectory);
}
/* Free argument list */
FreeArgs(anchor);
} else PrintFault(IoErr(), argv0); /* ReadArgs() failed */
return rc;
}